//-----------------------------------------------------------------------------
//   File:      bulkloop.c
//   Contents:  Hooks required to implement USB peripheral function.
//
// $Archive: /USB/Examples/FX2LP/bulkloop/bulkloop.c $
// $Date: 3/23/05 2:55p $
// $Revision: 4 $
//
//
//-----------------------------------------------------------------------------
// Copyright 2003, Cypress Semiconductor Corporation
//-----------------------------------------------------------------------------
#pragma NOIV               // Do not generate interrupt vectors

#include "fx2.h"
#include "fx2regs.h"
#include "syncdly.h"            // SYNCDELAY macro
#include "interrupciones.h"     // Rutinas de interrupción
#include "I2C.h"     			// Rutinas de I2C

extern BOOL GotSUD;             // Received setup data flag
extern BOOL Sleep;
extern BOOL Rwuen;
extern BOOL Selfpwr;

BYTE Configuration;             // Current configuration
BYTE AlternateSetting;          // Alternate settings

/*
xdata BYTE i2cdata[16];
static WORD xdata LED_Count = 0;
static BYTE xdata LED_Status = 0;
*/
BOOL in_enable = FALSE;         // flag to enable IN transfers
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
/*
#define FRAME_25fps			0xaa // 40mS  -> Blink
#define FRAME_12_5fps 		0xab // 80mS  -> Blink
#define FRAME_6_25fps  		0xac // 160mS -> Blink
#define FRAME_3_12fps		0xad // 320mS -> Blink
*/
#define SET_PULSADO_ESCOPIA		0xaa // Habilita el disparo por el pedal de escopia
#define SET_PULSADO_CINE		0xab // Habilita el disparo por el pedal de cine
#define SET_TEST_PULSADO		0xac // Prueba de pulsado autogenerado sin escopia
#define SET_FPS_PULSADO			0xad // FPS en pulsado autogenerado
#define SET_DELTA_MAS   		0xae // DELTA MAS	
#define SET_DELTA_MENOS 		0xaf // DELTA MENOS
#define SET_DELTA 				0xb5 // DELTA SET
#define SET_SYNC_SOURCE			0xb6 // Tipo de SYNC SET
#define SET_ANCHO_PULSO			0xb7 // Ancho del Pulso

#define SET_ESTADO_RELE_AUX3	0xb8 // Fija el estado del Rele Aux 3
#define SET_ESTADO_RELE_IRIS	0xb9 // Fija el estado del Rele Iris
#define SET_ESTADO_RELE_HCINE	0xba // Fija el estado del Rele HCINE
#define SET_ESTADO_AUXOUT		0xbb // Fija el estado del puerto AUXOUT

#define GET_ESTADO_PEDALES		0xbc // Obtener estado de los pedales
#define GET_ESTADO_READY		0xbd // Obtener estado de la señal Ready
#define GET_ESTADO_AUXIN		0xbe // Obtener estado de la señal AUXIN
#define GET_ESTADO_VSYNC		0xbf // Obtener estado de la señal VSYNC
#define GET_ESTADO_CAMPO		0xc0 // Obtener estado de la señal Campo

#define SET_DIR_PUERTO_B_LIBRE  0xc1 // Fija el comportamiento del puerto B (entrada/salida) de los 3 puertos no utilizados. 
#define SET_PUERTO_B_LIBRE		0xc2 // Fija el estado del puerto B de los 3 puertos no utilizados. 
#define SET_DIR_PUERTO_A		0xc3 // Fija el comportamiento del puerto A (entrada/salida).
#define SET_PUERTO_A			0xc4 // Fija el estado del puerto A. 

#define GET_ESTADO_PUERTO_B		0xc5 // Obtener estado del puerto B.
#define GET_ESTADO_PUERTO_A		0xc6 // Obtener estado del puerto A.

#define SET_MODO_AUTO_GAIN    	0xc7 // Fija que puertos se usarán como indicadores de Ganancia Automática => Modo 1: PD5 (TriggerOut se descarta!) y PD6 (AuxOut); Modo 2: PB5 (IOB5) y PB6 (IOB6)
#define SET_PUERTO_AUTO_GAIN    0xc8
#define SET_ANALOG_AUTO_GAIN    0xc9 // Fija el valor del DAC

//--------------- Tipo de Sincronismo ------------------//
#define PULSO_EXTERNO				0
#define PULSO_CAMPO					1
#define PULSO_VERTICAL				2
#define PULSO_AUTOGENERADO			3
#define PULSO_DESHABILITADO			4
#define PULSO_EXTERNO_2				5
//--------------- Tipo de Sincronismo ------------------//

//----------- Estado PULSADA --------------------------//
#define ESTADO_PULSADA_IDLE			0
#define ESTADO_PULSADA_DESPLAZADO	1	//Espera la cantidad de ticks asignados en estado bajo y pone en estado alto el puerto antes de pasar a otro estado
#define ESTADO_PULSADA_OFF			2	//Vuelve al estado bajo
#define ESTADO_PULSADA_ESPERA		3	//Espera a que el pulso recibido se encuentre en estado bajo
//----------- Estado PULSADA --------------------------//

//----------- Pedales y estados -----------------------//
#define PEDAL_SCOPIA	0
#define PEDAL_GRABAMEM	1
#define PEDAL_CINE		2
	#define ESTADO_PEDAL_IDLE                           0
	#define ESTADO_PEDAL_POSIBLE_PRESIONADO             1
	#define ESTADO_PEDAL_POSIBLE_PRESIONADO_A_CONFIRMAR 2
	#define ESTADO_PEDAL_PRESIONADO                     3

#define NIVEL_PEDAL_PRESIONADO  0
//----------- Pedales y estados -----------------------//
	
//----------- Auto Gain -------------------------------//
#define AUTO_GAIN_OFF	0
#define AUTO_GAIN_1		1
#define AUTO_GAIN_2		2
//----------- Auto Gain -------------------------------//

sbit CINE = IOB ^ 0;   			// Señal de cine que viene de la pedalera (Entrada)
sbit SCOPIA = IOB ^ 1;			// Señal de scopia que viene de la pedalera (Entrada)
sbit AUXIN = IOB ^ 2;			// Señal auxiliar que viene del equipo de Rayos (Entrada)
sbit TRIGGER_EXT = IOB ^ 3;		// Señal de trigger que viene del equipo de Rayos (Entrada)
sbit GRABMEM = IOB ^ 4;			// Señal de grabación de imagen que viene de la pedalera (Entrada)
sbit PORTB_5 = IOB ^ 5;
sbit PORTB_6 = IOB ^ 6;
sbit PORTB_7 = IOB ^ 7;

sbit CAMPO	= IOD ^ 0;			// Señal de campo que se obtiene de la señal de video mediante la placa de interfaz (Entrada)
sbit VSYNC	= IOD ^ 1;			// Señal del sincronismo vertical que se obtiene de la señal de video mediante la placa de interfaz (Entrada)
sbit RELE_AUX3	= IOD ^ 2;		// Señal para conmutar el Rele auxiliar 3 (Salida)
sbit RELE_IRIS	= IOD ^ 3;		// Señal para conmutar el Rele Iris (Salida)
sbit RELE_HCINE	= IOD ^ 4;		// Señal para conmutar el Rele HCine (Salida)
sbit TRIGGER_OUT = IOD ^ 5;		// Señal de trigger para la cámara (Salida)
sbit AUXOUT = IOD ^ 6;			// Señal auxiliar (Salida)
sbit READY = IOD ^ 7;			// Señal ready que viene del equipo de Rayos (Entrada)

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
WORD 	packetSize;
unsigned int tiempo_ref_fps=20; //20 mSeg

unsigned int timer0_tick=0;
unsigned int timer1_tick=0;
unsigned int timer1_delay_disparo=0;
unsigned int timer1_tiempo_on_disparo=0;
unsigned int timer1_tiempo_on_disparo_retrasado=0;

unsigned int delta_tick_1=1;
unsigned int tiempo_on_salida_pulsada=5; //5mSeg => Base de tiempo 1mS
unsigned char estado_salida_pulsada=ESTADO_PULSADA_IDLE;
unsigned char estado_pedales[3]={ESTADO_PEDAL_IDLE, ESTADO_PEDAL_IDLE, ESTADO_PEDAL_IDLE};

unsigned char origen_pulso_entrada=PULSO_EXTERNO;
unsigned char modo_auto_gain=AUTO_GAIN_OFF;
unsigned char test_disparo=0;
unsigned char disparo_por_escopia=0;
unsigned char disparo_por_cine=0;
unsigned char estado_disparo_latch=1;
															
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
void timer0_init (void);
void timer1_init (void);
void InicializarPuertos(void);
void AntiRebotePedales(unsigned char pedal);

//-----------------------------------------------------------------------------
//INTERRUPCIONES
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Task Dispatcher hooks
//   The following hooks are called by the task dispatcher.
//-----------------------------------------------------------------------------
void TD_Init(void)             // Called once at startup
{
	// set the CPU clock to 48MHz
   	CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1);
	
	InicializarPuertos();
		
	timer0_init ();
	timer1_init ();	
}

void TD_Poll(void)              // Called repeatedly while the device is idle
{		
	//-------------------------------- Pedaleras  ------------------------------//
	if(timer0_tick>=1)
	{
		AntiRebotePedales(PEDAL_SCOPIA);		
		AntiRebotePedales(PEDAL_GRABAMEM);
		AntiRebotePedales(PEDAL_CINE);				

		timer0_tick=0;
	}	
	//-------------------------------- Pedaleras  ------------------------------//

	if(modo_auto_gain!=AUTO_GAIN_1) //Deshabilita el puerto de disparo en caso de usar el modo de Auto Ganancia en 1
	{
		//------------ Señal de disparo a la cámara con retardo configurable ------//
		switch(estado_salida_pulsada)
		{	
			case ESTADO_PULSADA_IDLE:
			{
				switch(origen_pulso_entrada)
				{
					case PULSO_EXTERNO:
					{
						if(TRIGGER_EXT)
						{
							timer1_tick=0;
							timer1_tiempo_on_disparo=0;
							timer1_delay_disparo=0;
							estado_salida_pulsada=ESTADO_PULSADA_DESPLAZADO;							
						}
	
						break;
					}
	
					case PULSO_CAMPO:
					{
						if(CAMPO && ((estado_pedales[PEDAL_SCOPIA]==ESTADO_PEDAL_PRESIONADO)||(estado_pedales[PEDAL_CINE]==ESTADO_PEDAL_PRESIONADO)))
						//if(CAMPO && ((estado_pedales[PEDAL_SCOPIA]==ESTADO_PEDAL_PRESIONADO)||(estado_pedales[PEDAL_CINE]==ESTADO_PEDAL_PRESIONADO)))
						//if(CAMPO)
						{							
							timer1_tick=0;
							timer1_tiempo_on_disparo=0;
							timer1_delay_disparo=0; 
							TRIGGER_OUT=1; //Salida de Trigger para el equipo de Rayos															
							estado_salida_pulsada=ESTADO_PULSADA_DESPLAZADO;													
						}
	
						break;
					}
		               
					case PULSO_VERTICAL:
					{
						if(!VSYNC && ((estado_pedales[PEDAL_SCOPIA]==ESTADO_PEDAL_PRESIONADO)||(estado_pedales[PEDAL_CINE]==ESTADO_PEDAL_PRESIONADO)))
						//if(!VSYNC && (estado_pedales[PEDAL_SCOPIA]==ESTADO_PEDAL_PRESIONADO||estado_pedales[PEDAL_CINE]==ESTADO_PEDAL_PRESIONADO))
						{
							timer1_tick=0;
							timer1_tiempo_on_disparo=0;
							timer1_delay_disparo=0;	
							TRIGGER_OUT=1; //Salida de Trigger para el equipo de Rayos															
							estado_salida_pulsada=ESTADO_PULSADA_DESPLAZADO;													
						}
	
						break;
					}

					case PULSO_AUTOGENERADO:
					{
						if(((estado_pedales[PEDAL_SCOPIA]==ESTADO_PEDAL_PRESIONADO)&&(disparo_por_escopia))||((estado_pedales[PEDAL_CINE]==ESTADO_PEDAL_PRESIONADO)&&disparo_por_cine)||(test_disparo))
						{
							if(timer1_tick>=tiempo_ref_fps)
							{
								timer1_tick=0;
								timer1_tiempo_on_disparo=0;
								timer1_delay_disparo=0;								
								estado_salida_pulsada=ESTADO_PULSADA_DESPLAZADO;
								TRIGGER_OUT=1; //Salida de Trigger para el equipo de Rayos															
							}
						}

						break;
					}

					case PULSO_EXTERNO_2:
					{
						if(!TRIGGER_EXT)
						{
							timer1_tick=0;
							timer1_tiempo_on_disparo=0;
							timer1_delay_disparo=0;	
							//disparo_externo_2_latch=0;						
							//TRIGGER_OUT=1; //Salida de Trigger para probar
							estado_salida_pulsada=ESTADO_PULSADA_DESPLAZADO;														
						}

						break;
					}
				}
		
				break;
			}
	
			case ESTADO_PULSADA_DESPLAZADO:
			{
				switch(origen_pulso_entrada)
				{
					default:
					{
						//----------------- Delay trigger cámara ------------------//
						if(timer1_delay_disparo>=delta_tick_1)
						{
							estado_salida_pulsada=ESTADO_PULSADA_OFF;	
							AUXOUT=1;
							
							//TRIGGER_OUT=0; //Salida de Trigger para el equipo de Rayos
							timer1_tiempo_on_disparo_retrasado=0;						
						}				
						//----------------- Delay trigger cámara ------------------//
						
						//----------------- Tiempo en On Trigger Rx --------------//
						if(timer1_tiempo_on_disparo>=tiempo_on_salida_pulsada)
							TRIGGER_OUT=0; //Salida de Trigger para el equipo de Rayos				   	
						//----------------- Tiempo en On Trigger Rx --------------//
							
						break;
					}

					case PULSO_EXTERNO_2:
					{
						if(timer1_delay_disparo>=delta_tick_1)
						{
							estado_disparo_latch=0;
							timer1_tiempo_on_disparo_retrasado=0;
						    estado_salida_pulsada=ESTADO_PULSADA_OFF;
							TRIGGER_OUT=1;
						}
						break;
					}

					case PULSO_CAMPO:
					{
						//----------------- Delay trigger cámara ------------------//
						if(timer1_delay_disparo>=delta_tick_1)
						{
							AUXOUT=1;							
							timer1_tiempo_on_disparo_retrasado=0;						
							estado_disparo_latch=0;
							estado_salida_pulsada=ESTADO_PULSADA_OFF;
						}				
						//----------------- Delay trigger cámara ------------------//
						
						//----------------- Tiempo en On Trigger Rx --------------//
						if(timer1_tiempo_on_disparo>=tiempo_on_salida_pulsada)
							TRIGGER_OUT=0; //Salida de Trigger para el equipo de Rayos				   	
						//----------------- Tiempo en On Trigger Rx --------------//

						break;
					}

					case PULSO_VERTICAL:
					{
						//----------------- Delay trigger cámara ------------------//
						if(timer1_delay_disparo>=delta_tick_1)
						{
							AUXOUT=1;							
							//TRIGGER_OUT=0; //Salida de Trigger para el equipo de Rayos
							timer1_tiempo_on_disparo_retrasado=0;						
							estado_disparo_latch=0;
							estado_salida_pulsada=ESTADO_PULSADA_OFF;
						}				
						//----------------- Delay trigger cámara ------------------//
						
						//----------------- Tiempo en On Trigger Rx --------------//
						if(timer1_tiempo_on_disparo>=tiempo_on_salida_pulsada)
							TRIGGER_OUT=0; //Salida de Trigger para el equipo de Rayos				   	
						//----------------- Tiempo en On Trigger Rx --------------//

						break;
					}
				}
								
				break;
			}
	
			case ESTADO_PULSADA_OFF:
			{
				switch(origen_pulso_entrada)
				{
					default:
					{
						//----------------- Tiempo en On Trigger Cámara --------------//
						if(timer1_tiempo_on_disparo_retrasado>=tiempo_on_salida_pulsada)
						{
							AUXOUT=0;	
							estado_salida_pulsada=ESTADO_PULSADA_ESPERA;
							
							TRIGGER_OUT=0; //Salida de Trigger para el equipo de Rayos								
						}				
						//----------------- Tiempo en On Trigger Cámara --------------//
		
						//----------------- Tiempo en On Trigger Rx --------------//
						if(timer1_tiempo_on_disparo>=tiempo_on_salida_pulsada)
							TRIGGER_OUT=0; //Salida de Trigger para el equipo de Rayos				   	
						//----------------- Tiempo en On Trigger Rx --------------//
						break;
					}

					case PULSO_EXTERNO_2:
					{
						if(timer1_tiempo_on_disparo_retrasado>=(45+tiempo_on_salida_pulsada))
						{
							estado_disparo_latch=1;
							TRIGGER_OUT=0;
							estado_salida_pulsada=ESTADO_PULSADA_ESPERA;						
						}
						break;
					}

					case PULSO_CAMPO:
					{
						if(timer1_tiempo_on_disparo_retrasado>=(20+tiempo_on_salida_pulsada))
							estado_disparo_latch=1;							
						
						//----------------- Tiempo en On Trigger Cámara --------------//
						if(timer1_tiempo_on_disparo_retrasado>=tiempo_on_salida_pulsada)
						{
							AUXOUT=0;	
							TRIGGER_OUT=0; //Salida de Trigger para el equipo de Rayos
							estado_salida_pulsada=ESTADO_PULSADA_ESPERA;							
						}				
						//----------------- Tiempo en On Trigger Cámara --------------//
		
						//----------------- Tiempo en On Trigger Rx --------------//
						if(timer1_tiempo_on_disparo>=tiempo_on_salida_pulsada)
							TRIGGER_OUT=0; //Salida de Trigger para el equipo de Rayos				   	
						//----------------- Tiempo en On Trigger Rx --------------//

						break;
					}

					case PULSO_VERTICAL:
					{
						if(timer1_tiempo_on_disparo_retrasado>=(20+tiempo_on_salida_pulsada))
							estado_disparo_latch=1;																													
						
						//----------------- Tiempo en On Trigger Cámara --------------//
						if(timer1_tiempo_on_disparo_retrasado>=tiempo_on_salida_pulsada)
						{
							AUXOUT=0;	
							TRIGGER_OUT=0; //Salida de Trigger para el equipo de Rayos
							estado_salida_pulsada=ESTADO_PULSADA_ESPERA;							
						}				
						//----------------- Tiempo en On Trigger Cámara --------------//
		
						//----------------- Tiempo en On Trigger Rx --------------//
						if(timer1_tiempo_on_disparo>=tiempo_on_salida_pulsada)
							TRIGGER_OUT=0; //Salida de Trigger para el equipo de Rayos				   	
						//----------------- Tiempo en On Trigger Rx --------------//

						break;
					}
				}
				
				break;
			}
	
			case ESTADO_PULSADA_ESPERA:
			{
				switch(origen_pulso_entrada)
				{
					case PULSO_EXTERNO:
					{
						if(!TRIGGER_EXT)
							estado_salida_pulsada=ESTADO_PULSADA_IDLE;
						
						break;
					}
	
					case PULSO_CAMPO:
					{
						if(timer1_tiempo_on_disparo_retrasado>=(20+tiempo_on_salida_pulsada))
							estado_disparo_latch=1;							

						if(!CAMPO  && (((estado_pedales[PEDAL_SCOPIA]!=ESTADO_PEDAL_PRESIONADO)&&(estado_pedales[PEDAL_CINE]!=ESTADO_PEDAL_PRESIONADO))||(timer1_tick>=(tiempo_ref_fps-5))))
						//if(!CAMPO)
						{
							estado_salida_pulsada=ESTADO_PULSADA_IDLE;
							estado_disparo_latch=1;
						}																		
																		
						break;
					}
	
					case PULSO_VERTICAL:
					{
						if(timer1_tiempo_on_disparo_retrasado>=(20+tiempo_on_salida_pulsada))
							estado_disparo_latch=1;

						if(VSYNC && (((estado_pedales[PEDAL_SCOPIA]!=ESTADO_PEDAL_PRESIONADO)&&(estado_pedales[PEDAL_CINE]!=ESTADO_PEDAL_PRESIONADO))||(timer1_tick>=(tiempo_ref_fps-5))))
						{
							estado_salida_pulsada=ESTADO_PULSADA_IDLE;
							estado_disparo_latch=1;
						}
						else
							estado_disparo_latch=0;				
	
						break;
					}

					case PULSO_AUTOGENERADO:
					{
						if((estado_pedales[PEDAL_SCOPIA]!=ESTADO_PEDAL_PRESIONADO)||(estado_pedales[PEDAL_CINE]!=ESTADO_PEDAL_PRESIONADO)||(timer1_tick<tiempo_ref_fps))
							estado_salida_pulsada=ESTADO_PULSADA_IDLE;														

						break;
					}

					case PULSO_EXTERNO_2:
					{
						if(TRIGGER_EXT)
						{
							estado_salida_pulsada=ESTADO_PULSADA_IDLE;
							estado_disparo_latch=1;
						}
						else
							estado_disparo_latch=0;

						break;
					}
				}
						
				break;
			}
		}
		//------------ Señal de disparo a la cámara con retardo configurable ------//	
	}//if(modo_auto_gain!=AUTO_GAIN_1)			
}

BOOL TD_Suspend(void)          // Called before the device goes into suspend mode
{
   return(TRUE);
}

BOOL TD_Resume(void)          // Called after the device resumes
{
   return(TRUE);
}

//-----------------------------------------------------------------------------
// Device Request hooks
//   The following hooks are called by the end point 0 device request parser.
//-----------------------------------------------------------------------------

BOOL DR_GetDescriptor(void)
{
   return(TRUE);
}

BOOL DR_SetConfiguration(void)   // Called when a Set Configuration command is received
{
   Configuration = SETUPDAT[2];
   return(TRUE);            // Handled by user code
}

BOOL DR_GetConfiguration(void)   // Called when a Get Configuration command is received
{
   EP0BUF[0] = Configuration;
   EP0BCH = 0;
   EP0BCL = 1;
   return(TRUE);            // Handled by user code
}

BOOL DR_SetInterface(void)       // Called when a Set Interface command is received
{
   AlternateSetting = SETUPDAT[2];
   return(TRUE);            // Handled by user code
}

BOOL DR_GetInterface(void)       // Called when a Set Interface command is received
{
   EP0BUF[0] = AlternateSetting;
   EP0BCH = 0;
   EP0BCL = 1;
   return(TRUE);            // Handled by user code
}

BOOL DR_GetStatus(void)
{
   return(TRUE);
}

BOOL DR_ClearFeature(void)
{
   return(TRUE);
}

BOOL DR_SetFeature(void)
{
   return(TRUE);
}
//-----------------------------------------------------------------------------
//COMANDOS:
//-----------------------------------------------------------------------------
BOOL DR_VendorCmnd(void)
{
	switch (SETUPDAT[1])
	{
		//------------------- Pulsos Auto-Generados ---------------------------//
		/*
		case FRAME_25fps:  //0xaa
		{
			tiempo_ref_fps=40;
			*EP0BUF = (tiempo_ref_fps>>8);
			*(EP0BUF+1) = (tiempo_ref_fps&0xff);
			EP0BCH = 0;
			EP0BCL = 2;
			EP0CS |= bmHSNAK;
			break; 
		}
		case FRAME_12_5fps:	//0xab	   
		{
			tiempo_ref_fps=80;			
			*EP0BUF = (tiempo_ref_fps>>8);
			*(EP0BUF+1) = (tiempo_ref_fps&0xff);						
			EP0BCH = 0;
			EP0BCL = 2;
			EP0CS |= bmHSNAK;
			break;
		}
		case FRAME_6_25fps:  //0xac
		{
			tiempo_ref_fps=160;
			*EP0BUF = (tiempo_ref_fps>>8);
			*(EP0BUF+1) = (tiempo_ref_fps&0xff);
			EP0BCH = 0;
			EP0BCL = 2;
			EP0CS |= bmHSNAK;
			break;
		}
		case FRAME_3_12fps:   //0xad
		{
			tiempo_ref_fps=320;
			*EP0BUF = (tiempo_ref_fps>>8);
			*(EP0BUF+1) = (tiempo_ref_fps&0xff);
			EP0BCH = 0;
			EP0BCL = 2;
			EP0CS |= bmHSNAK;
			break;
		}
		*/
		case SET_PULSADO_ESCOPIA:
		{
			disparo_por_escopia=SETUPDAT[2];

			*EP0BUF = (unsigned char)(disparo_por_escopia); //Devuelve el valor de la variable disparo_por_escopia
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;			
			break;
		}

		case SET_PULSADO_CINE:
		{
			disparo_por_cine=SETUPDAT[2];

			*EP0BUF = (unsigned char)(disparo_por_cine); //Devuelve el valor de la variable disparo_por_cine
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;			
			break;
		}

		case SET_TEST_PULSADO:
		{
			test_disparo=SETUPDAT[2];

			*EP0BUF = (unsigned char)(test_disparo); //Devuelve el valor de la variable test_disparo
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;			
			break;
		}

		case SET_FPS_PULSADO:   //0xad
		{
			switch(SETUPDAT[2])
			{
				case 0:{tiempo_ref_fps=40; break;} 	//25FPS
				case 1:{tiempo_ref_fps=80; break;} 	//12.5FPS
				case 2:{tiempo_ref_fps=160; break;} //6.25FPS
				case 3:{tiempo_ref_fps=320; break;} //3.125FPS
				case 4:{tiempo_ref_fps=33; break;} 	//30FPS
				case 5:{tiempo_ref_fps=66; break;} 	//15FPS
				case 6:{tiempo_ref_fps=133; break;} //7.5FPS
				case 7:{tiempo_ref_fps=266; break;} //3.75FPS
				default:{tiempo_ref_fps=40; break;}	//25FPS
			}
			
			*EP0BUF = (tiempo_ref_fps>>8);
			*(EP0BUF+1) = (tiempo_ref_fps&0xff);
			EP0BCH = 0;
			EP0BCL = 2;
			EP0CS |= bmHSNAK;
			break;
		}
				
		//------------------- Pulsos Auto-Generados ---------------------------//
		
		//------------------- Corrimiento entre Trigger Recibido/Rx y Trigger Cámara ----//
		case SET_DELTA_MAS:
		{
			delta_tick_1++;
			if(delta_tick_1>19)
				delta_tick_1=19;

			*EP0BUF = (unsigned char)(delta_tick_1); //Devuelve el valor para saber el desplazamiento actual
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}

		case SET_DELTA_MENOS:
		{
			delta_tick_1--;
			if(delta_tick_1==0)
				delta_tick_1=1;

			*EP0BUF = (unsigned char)(delta_tick_1); //Devuelve el valor para saber el desplazamiento actual
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}
		
		case SET_DELTA:
		{
			if((SETUPDAT[2]>=0) && (SETUPDAT[2]<200))
				delta_tick_1=SETUPDAT[2];

			*EP0BUF = (unsigned char)(delta_tick_1); //Devuelve el valor para saber el desplazamiento actual
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}		
	    //------------------- Corrimiento entre Trigger Recibido/Rx y Trigger Cámara ----//

		case SET_SYNC_SOURCE:
		{
			if((SETUPDAT[2]>=0) && (SETUPDAT[2]<=PULSO_EXTERNO_2))
				origen_pulso_entrada=SETUPDAT[2];
			else
				origen_pulso_entrada=PULSO_DESHABILITADO;

			*EP0BUF = (unsigned char)(origen_pulso_entrada); //Devuelve el valor para saber el desplazamiento actual					

			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}

		case SET_ANCHO_PULSO:
		{
			if((SETUPDAT[2]>=0) && (SETUPDAT[2]<20))
				tiempo_on_salida_pulsada=SETUPDAT[2];

			*EP0BUF = (unsigned char)(tiempo_on_salida_pulsada); //Devuelve el valor para saber el desplazamiento actual
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}

		case GET_ESTADO_PEDALES:
		{
			*EP0BUF = estado_pedales[PEDAL_SCOPIA]; //Devuelve el estado de los pedales
			*(EP0BUF+1) = estado_pedales[PEDAL_GRABAMEM]; //Devuelve el estado de los pedales
			*(EP0BUF+2) = estado_pedales[PEDAL_CINE]; //Devuelve el estado de los pedales
			*(EP0BUF+3) = READY; //Devuelve el estado de ready!
			*(EP0BUF+4) = estado_disparo_latch;//TRIGGER_EXT; //Devuelve la entrada del trigger externo, Vsync y campo
			
			EP0BCH = 0;
			EP0BCL = 5;
			EP0CS |= bmHSNAK;
			break;
		}

		case GET_ESTADO_READY:
		{
			*EP0BUF = READY; //Devuelve el estado de la señal de Ready
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}

		case GET_ESTADO_AUXIN:
		{
			*EP0BUF = AUXIN; //Devuelve el estado de la señal de AUXIN
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}

		case GET_ESTADO_VSYNC:
		{
			*EP0BUF = VSYNC; //Devuelve el estado de la señal de VSYNC
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}

		case GET_ESTADO_CAMPO:
		{
			*EP0BUF = CAMPO; //Devuelve el estado de la señal de CAMPO
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}
		
		case SET_ESTADO_RELE_AUX3:
		{
			RELE_AUX3=SETUPDAT[2];
			*EP0BUF = RELE_AUX3; //Devuelve el estado de la señal de RELE_AUX3
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}

		case SET_ESTADO_RELE_IRIS:
		{
			RELE_IRIS=SETUPDAT[2];
			*EP0BUF = RELE_IRIS; //Devuelve el estado de la señal de RELE_IRIS
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}

		case SET_ESTADO_RELE_HCINE:
		{
			RELE_HCINE=SETUPDAT[2];
			*EP0BUF = RELE_HCINE; //Devuelve el estado de la señal de RELE_HCINE
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}

		case SET_ESTADO_AUXOUT:
		{
			AUXOUT=SETUPDAT[2];
			*EP0BUF = AUXOUT; //Devuelve el estado de la señal de AUXOUT
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}
		
		/*
		case SET_DIR_PUERTO_B_LIBRE:
		{
			OEB=(SETUPDAT[2]&0xE0); //Solo modifica la dirección de los puertos no utilizados!			
			*EP0BUF = OEB; //Devuelve la dirección del puerto B
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}

		case SET_PUERTO_B_LIBRE:
		{
			PORTB_5=(SETUPDAT[2]&0x20);
			PORTB_6=(SETUPDAT[2]&0x40);
			PORTB_7=(SETUPDAT[2]&0x80);

			*EP0BUF = IOB; //Devuelve el estado del puerto B			
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}
	    
		case SET_DIR_PUERTO_A:
		{
			OEA=SETUPDAT[2]; 
			*EP0BUF = OEA; //Devuelve la dirección del puerto A
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}

		case SET_PUERTO_A:
		{
			IOA=SETUPDAT[2]; 
			*EP0BUF = IOA; //Devuelve estado del puerto A
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}
		
		case GET_ESTADO_PUERTO_B:
		{
			*EP0BUF = IOB; //Devuelve el estado de la señal de Ready
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}
	   	
		case GET_ESTADO_PUERTO_A:
		{
			*EP0BUF = IOA; //Devuelve el estado de la señal de Ready
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
			break;
		}
		*/
		case SET_MODO_AUTO_GAIN:
		{
			modo_auto_gain=SETUPDAT[2]; 
			*EP0BUF = SETUPDAT[2]; //Devuelve el modo de Ganancia Automática
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;
		   	
			switch(modo_auto_gain)
			{
				case AUTO_GAIN_1:
				{
					TRIGGER_OUT=0;
					AUXOUT=0;	
					break;
				}

				case AUTO_GAIN_2:
				{
					OEB |= 0X60; //Puerto B5 y B6 como salidas
					PORTB_5=0;
					PORTB_6=0;
					break;
				}
			}
			
			break;
		}

		case SET_PUERTO_AUTO_GAIN:
		{
			switch(modo_auto_gain)
			{
				case AUTO_GAIN_1:
				{
					TRIGGER_OUT=SETUPDAT[2];
					AUXOUT=SETUPDAT[3];	
					break;
				}

				case AUTO_GAIN_2:
				{
					PORTB_5=SETUPDAT[2];
					PORTB_6=SETUPDAT[3];
					break;
				}
			}

			*EP0BUF = SETUPDAT[2]; //Devuelve el estado de los pedales
			*(EP0BUF+1) = SETUPDAT[3]; //Devuelve el estado de los pedales
			EP0BCH = 0;
			EP0BCL = 2;
			EP0CS |= bmHSNAK;

			break;
		}

		case SET_ANALOG_AUTO_GAIN:
		{
			*EP0BUF = SetDAC5571(SETUPDAT[2], SETUPDAT[3]); //Devuelve el resultado de la escritura del I2C, 0: Ok, 1: Error
			EP0BCH = 0;
			EP0BCL = 1;
			EP0CS |= bmHSNAK;

			break;
		}

		default:
			return(TRUE);
	}
	return(FALSE);
}

//-----------------------------------------------------------------------------
// USB Interrupt Handlers
//   The following functions are called by the USB interrupt jump table.
//-----------------------------------------------------------------------------

// Setup Data Available Interrupt Handler
void ISR_Sudav(void) interrupt 0
{
   // enable the automatic length feature of the Setup Data Autopointer
   // in case a previous transfer disbaled it
   SUDPTRCTL |= bmSDPAUTO;
   GotSUD = TRUE;            // Set flag
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSUDAV;         // Clear SUDAV IRQ
}

// Setup Token Interrupt Handler
void ISR_Sutok(void) interrupt 0
{
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSUTOK;         // Clear SUTOK IRQ
}

void ISR_Sof(void) interrupt 0
{
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSOF;            // Clear SOF IRQ
}

void ISR_Ures(void) interrupt 0
{
   if (EZUSB_HIGHSPEED())
   {
      pConfigDscr = pHighSpeedConfigDscr;
      pOtherConfigDscr = pFullSpeedConfigDscr;
      packetSize = 512;

   }
   else
   {
      pConfigDscr = pFullSpeedConfigDscr;
      pOtherConfigDscr = pHighSpeedConfigDscr;
      packetSize = 64;
   }
   
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmURES;         // Clear URES IRQ
}

void ISR_Susp(void) interrupt 0
{
   Sleep = TRUE;
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSUSP;
}

void ISR_Highspeed(void) interrupt 0
{
   if (EZUSB_HIGHSPEED())
   {
      pConfigDscr = pHighSpeedConfigDscr;
      pOtherConfigDscr = pFullSpeedConfigDscr;
      packetSize = 512;

   }
   else
   {
      pConfigDscr = pFullSpeedConfigDscr;
      pOtherConfigDscr = pHighSpeedConfigDscr;
      packetSize = 64;
   }

   EZUSB_IRQ_CLEAR();
   USBIRQ = bmHSGRANT;
}

// This function enables Timer 0. Timer 0 generates a synchronous interrupt
// once every 100Hz or 10 ms.
void timer0_init (void)
{
	EA = 0; // disables all interrupts
	timer0_tick = 0;
	TR0 = 0; // stops Timer 0
	CKCON = 0x03; // Timer 0 using CLKOUT/12
	TMOD &= ~0x0F; // clear Timer 0 mode bits
	TMOD |= 0x01; // setup Timer 0 as a 16-bit timer
	TL0 = (TIMER0_COUNT & 0x00FF); // loads the timer counts
	TH0 = (TIMER0_COUNT >> 8);
	PT0 = 0; // sets the Timer 0 interrupt to low priority
	ET0 = 1; // enables Timer 0 interrupt
	TR0 = 1; // starts Timer 0
	EA = 1; // enables all interrupts
}

// This function enables Timer 1. Timer 1 generates a synchronous interrupt
// once every 1000Hz or 1 ms.
void timer1_init (void)
{
	EA = 0; // disables all interrupts
	timer1_tick = 0;
	TR1 = 0; // stops Timer 0
	CKCON = 0x03; // Timer 0 using CLKOUT/12
	TMOD &= ~0xF0; // clear Timer 1 and 1 mode bits
	TMOD |= 0x10; // setup Timer 1 as a 16-bit timer
	TL1 = (TIMER1_COUNT & 0x00FF); // loads the timer counts
	TH1 = (TIMER1_COUNT >> 8);
	PT1 = 0; // sets the Timer 0 interrupt to low priority
	ET1 = 1; // enables Timer 0 interrupt
	
	TR1 = 1; // starts Timer 1
	EA = 1; // enables all interrupts
}

void InicializarPuertos()
{
	/*
	sbit CINE = IOB ^ 0;   			// Señal de cine que viene de la pedalera (Entrada)
	sbit SCOPIA = IOB ^ 1;			// Señal de scopia que viene de la pedalera (Entrada)
	sbit AUXIN = IOB ^ 2;			// Señal auxiliar que viene del equipo de Rayos (Entrada)
	sbit TRIGGER_EXT = IOB ^ 3;		// Señal de trigger que viene del equipo de Rayos (Entrada)
	sbit GRABMEM = IOB ^ 4;			// Señal de grabación de imagen que viene de la pedalera (Entrada)
	sbit LED_TESTIGO = IOB ^ 7;
	
	sbit CAMPO	= IOD ^ 0;			// Señal de campo que se obtiene de la señal de video mediante la placa de interfaz (Entrada)
	sbit VSYNC	= IOD ^ 1;			// Señal del sincronismo vertical que se obtiene de la señal de video mediante la placa de interfaz (Entrada)
	sbit RELE_AUX3	= IOD ^ 2;		// Señal para conmutar el Rele auxiliar 3 (Salida)
	sbit RELE_IRIS	= IOD ^ 3;		// Señal para conmutar el Rele Iris (Salida)
	sbit RELE_HCINE	= IOD ^ 4;		// Señal para conmutar el Rele HCine (Salida)
	sbit TRIGGER_OUT = IOD ^ 5;		// Señal de trigger para la cámara (Salida)
	sbit AUXOUT = IOD ^ 6;			// Señal auxiliar (Salida)
	sbit READY = IOD ^ 7;			// Señal ready que viene del equipo de Rayos (Entrada)
	*/
	
	//------------ Puerto A ----------------------//
	OEA=0x00; //Puerto A como entrada
	//------------ Puerto A ----------------------//

	//------------ Puerto B ----------------------//	
	OEB = 0X00; //Puerto B como entrada
	SCOPIA=1;
	GRABMEM=1;
	CINE=1;
	AUXIN=1;
	TRIGGER_EXT=1;
	GRABMEM=1;
	//------------ Puerto B ----------------------//

	//------------ Puerto D ----------------------//
	OED =0X7C; //PD0, PD1 y PD7: entradas; PD2, PD3, PD4, PD5, PD6: salidas
	CAMPO=1;
	VSYNC=1;
	READY=1;

	RELE_AUX3=0;
	RELE_IRIS=0;
	RELE_HCINE=0;
	TRIGGER_OUT=0;
	AUXOUT=0;
	//------------ Puerto D ----------------------//	
}

void AntiRebotePedales(unsigned char pedal)
{
    bit ret;

    switch(estado_pedales[pedal])
    {
        case ESTADO_PEDAL_IDLE:
        {
            switch(pedal)
			{
				case PEDAL_SCOPIA:
				{
					ret=SCOPIA;
					break;
				}

				case PEDAL_GRABAMEM:
				{
					ret=GRABMEM;
					break;
				}

				case PEDAL_CINE:
				{
					ret=CINE;
					break;
				}
			}

            if(ret==NIVEL_PEDAL_PRESIONADO)
                estado_pedales[pedal]=ESTADO_PEDAL_POSIBLE_PRESIONADO;
            break;
        }

        case ESTADO_PEDAL_POSIBLE_PRESIONADO:
        {
            switch(pedal)
			{
				case PEDAL_SCOPIA:
				{
					ret=SCOPIA;
					break;
				}

				case PEDAL_GRABAMEM:
				{
					ret=GRABMEM;
					break;
				}

				case PEDAL_CINE:
				{
					ret=CINE;
					break;
				}
			}

			if(ret==NIVEL_PEDAL_PRESIONADO)
                estado_pedales[pedal]=ESTADO_PEDAL_POSIBLE_PRESIONADO_A_CONFIRMAR;           
            else
                estado_pedales[pedal]=ESTADO_PEDAL_IDLE;   //Rebote

            break;
        }

        case ESTADO_PEDAL_POSIBLE_PRESIONADO_A_CONFIRMAR:
        {
            switch(pedal)
			{
				case PEDAL_SCOPIA:
				{
					ret=SCOPIA;
					break;
				}

				case PEDAL_GRABAMEM:
				{
					ret=GRABMEM;
					break;
				}

				case PEDAL_CINE:
				{
					ret=CINE;
					break;
				}
			}
			
			if(ret==NIVEL_PEDAL_PRESIONADO)
                estado_pedales[pedal]=ESTADO_PEDAL_PRESIONADO;           
            else
                estado_pedales[pedal]=ESTADO_PEDAL_IDLE;   //Rebote

            break;
        }

        case ESTADO_PEDAL_PRESIONADO:
        {
            switch(pedal)
			{
				case PEDAL_SCOPIA:
				{
					ret=SCOPIA;
					break;
				}

				case PEDAL_GRABAMEM:
				{
					ret=GRABMEM;
					break;
				}

				case PEDAL_CINE:
				{
					ret=CINE;
					break;
				}
			}			

            if(ret!=NIVEL_PEDAL_PRESIONADO)
				estado_pedales[pedal]=ESTADO_PEDAL_IDLE;
                
            break;
        }
    }
}


void ISR_Ep0ack(void) interrupt 0
{
}
void ISR_Stub(void) interrupt 0
{
}
void ISR_Ep0in(void) interrupt 0
{
}
void ISR_Ep0out(void) interrupt 0
{
}
void ISR_Ep1in(void) interrupt 0
{
}
void ISR_Ep1out(void) interrupt 0
{
}
void ISR_Ep2inout(void) interrupt 0
{
}
void ISR_Ep4inout(void) interrupt 0
{
}
void ISR_Ep6inout(void) interrupt 0
{
}
void ISR_Ep8inout(void) interrupt 0
{
}
void ISR_Ibn(void) interrupt 0
{
}
void ISR_Ep0pingnak(void) interrupt 0
{
}
void ISR_Ep1pingnak(void) interrupt 0
{
}
void ISR_Ep2pingnak(void) interrupt 0
{
}
void ISR_Ep4pingnak(void) interrupt 0
{
}
void ISR_Ep6pingnak(void) interrupt 0
{
}
void ISR_Ep8pingnak(void) interrupt 0
{
}
void ISR_Errorlimit(void) interrupt 0
{
}
void ISR_Ep2piderror(void) interrupt 0
{
}
void ISR_Ep4piderror(void) interrupt 0
{
}
void ISR_Ep6piderror(void) interrupt 0
{
}
void ISR_Ep8piderror(void) interrupt 0
{
}
void ISR_Ep2pflag(void) interrupt 0
{
}
void ISR_Ep4pflag(void) interrupt 0
{
}
void ISR_Ep6pflag(void) interrupt 0
{
}
void ISR_Ep8pflag(void) interrupt 0
{
}
void ISR_Ep2eflag(void) interrupt 0
{
}
void ISR_Ep4eflag(void) interrupt 0
{
}
void ISR_Ep6eflag(void) interrupt 0
{
}
void ISR_Ep8eflag(void) interrupt 0
{
}
void ISR_Ep2fflag(void) interrupt 0
{
}
void ISR_Ep4fflag(void) interrupt 0
{
}
void ISR_Ep6fflag(void) interrupt 0
{
}
void ISR_Ep8fflag(void) interrupt 0
{
}
void ISR_GpifComplete(void) interrupt 0
{
}
void ISR_GpifWaveform(void) interrupt 0
{
}

